/**********************************************************************************************************************************************/

//PID算法温控C语言


#include "pid.h"
#include "max31865.h"
#include<math.h>
#include<string.h>
//Ticker tiker_pwm;
double compute_temp(unsigned int adc_code,unsigned int bottom,unsigned int top);
struct PID
{
    double SetPoint ;
    // 设定目标 Desired Value
    double Proportion ;
    // 比例常数 Proportional Const
    double Integral ;
    // 积分常数 Integral Const
    double Derivative ;
    // 微分常数 Derivative Const
    double LastError ;
    // Error[-1]
    double PrevError ;
    // Error[-2]
    double SumError ;
    // Sums of Errors
}
;
struct PID spid ;
// PID Control Structure
double rout ;
// PID Response (Output)
double rin ;
// PID Feedback (Input)


//sbit output=P1^4;
DigitalOut output(PC_8);
unsigned char high_time,low_time,count=0 ;
//占空比调节参数
unsigned int set_temper=100 ;
double temper=0;
double current_temp_buf;

void PIDInit(struct PID *pp)
{
    memset(pp,0,sizeof(struct PID)); //PID参数初始化全部设置为0

	
}
void PIDSet(struct PID *spid_set)
{
	spid_set->SetPoint=100; 
	spid_set->Proportion=10;
	spid_set->Integral=10;
	spid_set->Derivative=0;
}
double PIDCalc(struct PID *sptr,double NextPoint)
{
		register double iError, iIncpid; //当前误差 
//printf("sptr->SetPoint2= %f .\n\r", sptr->SetPoint);	
		iError = sptr->SetPoint - NextPoint; //增量计算

//printf("NextPoint= %f .\n\r", NextPoint);	
//printf("iError= %f .\n\r", iError);	
		iIncpid = sptr->Proportion * iError //E[k]项 
		- sptr->Integral * sptr->LastError //E[k－1]项 
		+ sptr->Derivative * sptr->PrevError; //E[k－2]项 
//	printf("iIncpid= %f .\n\r", iIncpid);	
		//存储误差，用于下次计算 
		sptr->PrevError = sptr->LastError; 
		sptr->LastError = iError; 
		//返回增量值 
		return(iIncpid); 
	

}

/***********************************************************
温度比较处理子程序
***********************************************************/

unsigned char compare_temper(unsigned char chx)
{
	PIDBEGIN();
//printf("spid->SetPoint2= %f .\n\r", spid.SetPoint);
	temper=compute_temp((max31865_read_data(chx,0x01)<<7)+(max31865_read_data(chx,0x02)>>1),0,46);
    unsigned char i ;
    //EA=0;
    if(set_temper>temper)
    {
        if(set_temper-temper>1)
        {
            high_time=100 ; //大于1°不进行PID运算
            low_time=0 ;
        }
        else
        {   //在1°范围内进行PID运算
            for(i=0;i<10;i++)
            {
                //get_temper();
								
                rin=compute_temp((max31865_read_data(chx,0x01)<<7)+(max31865_read_data(chx,0x02)>>1),0,46);
							//	temper=rin;
								//rin=temper;
							//	printf("current temp 1 %f .\n\r", rin);
                // Read Input
                rout+=PIDCalc(&spid,rin); //执行PID运算
						//		printf("rout1= %f .\n\r", rout);
                // Perform PID Interation
            }
            if(high_time<=100)  //限制最大值
            high_time=(unsigned char)(rout/800);
            else
            high_time=100;
            low_time=(100-high_time);
				//		printf("high_time=%d .\n\r", high_time);
        }
    }
/****************************************/
    else if(set_temper<=temper) //当实际温度大于设置温度时
    {
        if(temper-set_temper>0)//如果实际温度大于设定温度
        {
            high_time=0 ;
            low_time=100 ;
        }
        else
        {
            for(i=0;i<10;i++)
            {
							
                //get_temper();
              rin=compute_temp((max31865_read_data(chx,0x01)<<7)+(max31865_read_data(chx,0x02)>>1),0,46);
						//	temper=rin;
							//rin=temper;
						//	printf("current temp 2 %f .\n\r", rin);
                // Read Input
                rout+=PIDCalc(&spid,rin);
					//		printf("rout2 = %f .\n\r", rout);
                // Perform PID Interation
            }
            if(high_time<100) //此变量是无符号字符型
            high_time=(unsigned char)(rout/10000);
            else
            high_time=0 ;//限制不输出负值
            low_time=(100-high_time);
				//		printf("low_time=%d .\n\r", low_time);
            //EA=1;
        }
    }
		

		printf("current_temp1 %f ", compute_temp((max31865_read_data(chx,0x01)<<7)+(max31865_read_data(chx,0x02)>>1),0,46));
		return high_time;
}


/*****************************************************
T0中断服务子程序，用于控制电平的翻转 ,40us*100=4ms周期
******************************************************/
//void pwm_serve()
//{
////    if(++count<=(high_time))
////         output=0 ;
////    else if(count<=100)
////    {
////        output=1 ;
////    }
////    else
////    count=0 ;
////printf("pulse_buf  6 .\n\r");
//}

void PIDBEGIN()
{
    high_time=50 ;
    low_time=50 ;
    PIDInit(&spid);
		PIDSet(&spid);
}

